package com.tanhua.commons.template;

import com.alibaba.fastjson.JSON;
import com.tanhua.commons.pojo.IMessage;
import com.tanhua.commons.properties.HuanXinProperties;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author liuyp
 * @date 2021/02/03
 */
@Slf4j
public class HuanXinTemplate {

    /**
     * token的有效期
     */
    private long expire = 0;
    /**
     * 环信的token
     */
    private String token;
    /**
     * 环信的url地址，需要我们根据环信的配置参数拼接得到
     */
    private String huanXinUrl;

    /**
     * Rest工具，用于向环信API发请求。环信的API都要求RESTful风格的请求
     */
    private RestTemplate restTemplate = new RestTemplate();

    private HuanXinProperties properties;

    public HuanXinTemplate(HuanXinProperties properties) {
        this.properties = properties;
        this.huanXinUrl = properties.getUrl() + properties.getOrgName() + "/" + properties.getAppName();
    }

    /**
     * 注册用户到环信
     *
     * @param id       要注册的环信id
     * @param password 要设置的环信密码
     */
    public boolean register(String id, String password) {
        String url = huanXinUrl + "/users";

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Authorization", "Bearer " + getToken());
        httpHeaders.add("Content-Type", "application/json");

        Map<String, Object> params = new HashMap<>();
        params.put("username", id);
        params.put("password", password);

        HttpEntity<Map> httpEntity = new HttpEntity<>(params, httpHeaders);

        ResponseEntity<String> response = restTemplate.postForEntity(url, httpEntity, String.class);

        return response.getStatusCode().value() == 200;
    }

    /**
     * 把好友关系注册到环信
     *
     * @param userId   用户id
     * @param friendId 好友id
     * @return 是否注册成功
     */
    public boolean addContactUser(Long userId, Long friendId) {

        String url = huanXinUrl + "/users/" + userId + "/contacts/users/" + friendId;

        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.add("Content-Type", "application/json");
        httpHeaders.add("Authorization", "Bearer " + getToken());

        HttpEntity entity = new HttpEntity(httpHeaders);

        ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

        return response.getStatusCode().value() == 200;
    }

    /**
     * 向某一用户发送消息
     *
     * @param friendId 好友id
     * @param message  消息内容。
     * @return 是否发送成功
     */
    public boolean sendMsg(String friendId, IMessage message) {

        String url = huanXinUrl + "/messages";

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/json");
        headers.add("Authorization", "Bearer " + getToken());

        Map<String, Object> body = new HashMap<>();
        body.put("target_type", "users");
        body.put("target", new String[]{friendId});

        Map<String, Object> msg = new HashMap<>();
        msg.put("type", "txt");
        msg.put("msg", JSON.toJSONString(message));

        body.put("msg", msg);

        HttpEntity<Map> entity = new HttpEntity<>(body, headers);

        ResponseEntity<String> response = restTemplate.postForEntity(url, entity, String.class);

        return response.getStatusCode().value() == 200;
    }

    /**
     * 从环信平台获取token。后续与环信交互时，都要携带token值到环信
     */
    public String getToken() {
        long now = System.currentTimeMillis();

        //如果token已过期，则再次发请求到环信，获取新的token
        if (now >= expire) {
            String url = huanXinUrl + "/token";

            //构造请求参数
            Map<String, Object> params = new HashMap<>();
            params.put("grant_type", "client_credentials");
            params.put("client_id", properties.getClientId());
            params.put("client_secret", properties.getClientSecret());

            //向环信平台发送POST方式的请求到url，并传参params，得到响应
            ResponseEntity<String> response = restTemplate.postForEntity(url, params, String.class);

            //获取环信响应回来的结果，是json格式的字符串
            String body = response.getBody();
            Map map = JSON.parseObject(body, Map.class);
            //  从响应结果里得到token
            token = (String) map.get("access_token");
            //  从响应结果里得到token的有效期，单位是秒
            Integer expiresIn = (Integer) map.get("expires_in");

            expire = System.currentTimeMillis() + expiresIn * 1000;
            log.info("重新获取环信token：{}，过期时间：{}", token, new Date(expire));
        }

        return token;
    }
}